package info.brenstar.boxedin.core;

import java.util.*;

import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.geom.Rectangle;

/**
 * A class for maintaining sprites. Provides methods to update, render, and kill sprites.
 * Dead sprites are removed every update.
 * @author Brenstar
 *
 */
public class SpriteGroup {
	private ArrayList<Sprite> sprites, deadsprites;
	private Room room;
	
	public SpriteGroup() {
		this.sprites = new ArrayList<Sprite>();
		this.deadsprites = new ArrayList<Sprite>();
	}
	
	public SpriteGroup(Room room) {
		this.sprites = new ArrayList<Sprite>();
		this.deadsprites = new ArrayList<Sprite>();
		this.room = room;
	}
	
	/**
	 * Calls the update method in all sprites that implement the Updated interface
	 */
	public void updateAll() {
		for (Iterator<Sprite> i = sprites.iterator(); i.hasNext();) {
			Sprite sprite = i.next();
			if (sprite instanceof Updated) {
				((Updated)sprite).update();
			}
		}
		deadsprites.clear();
	}
	
	/**
	 * Calls pollKeys method in sprites that implement the Controllable interface
	 * @param in an input object to send to the sprites
	 */
	public void pollInput(Input in) {
		for (Iterator<Sprite> i = sprites.iterator(); i.hasNext();) {
			Sprite sprite = i.next();
			if (sprite instanceof Controllable) {
				((Controllable)sprite).pollKeys(in);
			}
		}
	}
	
	/**
	 * Calls the render method in sprites that implement the Updated interface
	 * @param g A graphics object to pass
	 */
	public void renderAll(Graphics g) {
		for (Iterator<Sprite> i = sprites.iterator(); i.hasNext();) {
			Sprite sprite = i.next();
			if (sprite instanceof Updated) {
				((Updated)sprite).render(g);
			}
		}
	}
	
	/**
	 * Killing a sprites marks it for removal. This causes the sprite's onkill() method to be called, and
	 * the sprite will be removed on the next update.
	 * @param sprite
	 */
	public void kill(Sprite sprite) {
		if (sprites.contains(sprite)) {
			sprites.remove(sprite);
			sprite.kill();
			deadsprites.add(sprite);
		}
	}
	
	public void killAll() {
		for (Iterator<Sprite> i = sprites.iterator(); i.hasNext();) {
			Sprite sprite = i.next();
			sprite.kill();
			deadsprites.add(sprite);
		}
		sprites.clear();
	}
	
	/**
	 * Adds the sprite to the group if it is not already in the group
	 * @param sprite The sprite to add
	 */
	public void add(Sprite sprite) {
		if (!sprites.contains(sprite)) {
			sprites.add(sprite);
			sprite.assignGroup(this);
			sprite.setRoom(room);
		}
	}
	
	public ArrayList<Sprite> getAll() {
		return this.sprites;
	}
	

	public Room getRoom() {
		return room;
	}

	public void setRoom(Room room) {
		this.room = room;
	}
	
}
